/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package battleship.game;

import battleship.board.AbstractBoardSide;
import battleship.board.CannotPlaceShipException;
import battleship.ship.DirectionEnum;
import battleship.ship.Ship1;
import battleship.ship.Ship2;
import battleship.ship.Ship3;
import battleship.ship.Ship4;
import battleship.ship.Ship5;
import java.util.List;
import util.InputTaker;
import util.MsgPrinter;

/**
 *
 * @author ali
 */
public class StatePlayer1PlaceShips extends AbstractState {

    AbstractBoardSide board = Game.getHumanPlayer().getBoard();
    private static AbstractState instance;

    public static AbstractState getInstance() {
        if (instance == null) {
            instance = new StatePlayer1PlaceShips();
        }
        return instance;
    }

    @Override
    public void execute() {
        try {
            String playerName = Game.getHumanPlayer().getName();
            MsgPrinter.print(playerName + ", please place your ships on the board.");
            printInstructions();
            setShip1();
            setShip2();
            setShip3();
            setShip4();
            setShip5();
            MsgPrinter.print("Ships placed for " + Game.getHumanPlayer().getName());
        } catch (IllegalArgumentException ex) {
            ex.printStackTrace();
        }
    }

    @Override
    public StateType getNextState() {
        StatePlayer2PlaceShips statePlayer2PlaceShips = new StatePlayer2PlaceShips();
        return statePlayer2PlaceShips;
    }

    private ShipLocationAndDirection getShipLocationAndDirection(String shipName) {
        String msg = "Please input location (x y) for " + shipName + " : ";
        List<Integer> xy = InputTaker.takeInput(msg);
        msg = "Enter Direction (0=H, 1=V) : ";
        DirectionEnum dir = InputTaker.readDirection(msg);

        ShipLocationAndDirection locAndDIr = new ShipLocationAndDirection(xy.get(0), xy.get(1), dir);
        return locAndDIr;

    }

    private void setShip1() {
        try {
            ShipLocationAndDirection locAndDIr = getShipLocationAndDirection(Ship1.nameShip);
            int startX = locAndDIr.getX();
            int startY = locAndDIr.getY();
            Ship1 ship1 = new Ship1(startX, startY, locAndDIr.getDir());
            boolean shipPlacedOk = board.setShip(ship1, startX, startY);
            printShipPlacedMsg(Ship1.nameShip, startX, startY, locAndDIr.getDir());
        } catch (IllegalArgumentException ex) {
            MsgPrinter.print("Please use another location or direction. Try again.");
            setShip1();
        } catch (CannotPlaceShipException ex) {
            MsgPrinter.print("Please use another location or direction. Try again.");
            setShip1();
        }

    }

    private void setShip2() {
        try {
            ShipLocationAndDirection locAndDIr = getShipLocationAndDirection(Ship2.nameShip);
            int startX = locAndDIr.getX();
            int startY = locAndDIr.getY();
            Ship2 ship2 = new Ship2(startX, startY, locAndDIr.getDir());
            boolean shipPlacedOk = board.setShip(ship2, startX, startY);
            printShipPlacedMsg(Ship2.nameShip, startX, startY, locAndDIr.getDir());
        } catch (IllegalArgumentException ex) {
            MsgPrinter.print("Please use another location or direction. Try again.");
            setShip2();
        } catch (CannotPlaceShipException ex) {
            MsgPrinter.print("Please use another location or direction. Try again.");
            setShip2();
        }
    }

    private void setShip3() {
        try {
            ShipLocationAndDirection locAndDIr = getShipLocationAndDirection(Ship3.nameShip);
            int startX = locAndDIr.getX();
            int startY = locAndDIr.getY();
            Ship3 ship3 = new Ship3(startX, startY, locAndDIr.getDir());
            boolean shipPlacedOk = board.setShip(ship3, startX, startY);
            printShipPlacedMsg(Ship3.nameShip, startX, startY, locAndDIr.getDir());
        } catch (IllegalArgumentException ex) {
            MsgPrinter.print("Please use another location or direction. Try again.");
            setShip3();
        } catch (CannotPlaceShipException ex) {
            MsgPrinter.print("Please use another location or direction. Try again.");
            setShip3();
        }
    }

    private void setShip4() {
        try {
            ShipLocationAndDirection locAndDIr = getShipLocationAndDirection(Ship4.nameShip);
            int startX = locAndDIr.getX();
            int startY = locAndDIr.getY();
            Ship4 ship4 = new Ship4(startX, startY, locAndDIr.getDir());
            boolean shipPlacedOk = board.setShip(ship4, startX, startY);
            printShipPlacedMsg(Ship4.nameShip, startX, startY, locAndDIr.getDir());
        } catch (IllegalArgumentException ex) {
            MsgPrinter.print("Please use another location or direction. Try again.");
            setShip4();
        } catch (CannotPlaceShipException ex) {
            MsgPrinter.print("Please use another location or direction. Try again.");
            setShip4();
        }
    }

    private void setShip5() {
        try {
            ShipLocationAndDirection locAndDIr = getShipLocationAndDirection(Ship5.nameShip);
            int startX = locAndDIr.getX();
            int startY = locAndDIr.getY();
            Ship5 ship5 = new Ship5(startX, startY, locAndDIr.getDir());
            boolean shipPlacedOk = board.setShip(ship5, startX, startY);
            printShipPlacedMsg(Ship5.nameShip, startX, startY, locAndDIr.getDir());
        } catch (IllegalArgumentException ex) {
            MsgPrinter.print("Please use another location or direction. Try again.");
            setShip5();
        } catch (CannotPlaceShipException ex) {
            MsgPrinter.print("Please use another location or direction. Try again.");
            setShip5();
        }
    }

    private void printInstructions() {
        String msg = "Simply enter the coordinates of the location. For e.g.";
        msg = msg + "\n" + "1 2"
                + "\n"
                + "This will place the ship at x=1, y=2"
                + "\n"
                + "Then enter the direction of the ship as follows"
                + "\n"
                + "Direction : 0= Hori  and 1 = Verti"
                + "\n"
                + "If you enter direction = 0"
                + "\n"
                + "Then the ship will occupy locations"
                + "\n"
                + "{ (1,2), (2,2), (3,2), (4,2)....}"
                + "\n"
                + "...upto the ship's length"
                + "\n"
                + "-----------------------------------------"
                + "\n";
        MsgPrinter.print(msg);
    }

    private void printShipPlacedMsg(String shipName, int startX, int startY, DirectionEnum dir) {
        MsgPrinter.print(shipName 
                + " placed at : ["
                + Integer.toString(startX)
                + ", "
                + Integer.toString(startY)+"]"
                + " ; "+dir.toString());
        MsgPrinter.print("------");
    }

    private class ShipLocationAndDirection {

        private int x, y;
        private DirectionEnum dir;

        public ShipLocationAndDirection(int x, int y, DirectionEnum dir) {
            this.x = x;
            this.y = y;
            this.dir = dir;
        }

        public DirectionEnum getDir() {
            return dir;
        }

        public int getX() {
            return x;
        }

        public int getY() {
            return y;
        }
    }
}
